package com.uduemc.biso.module.basic.service.common.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.core.common.extities.CCustomerData;
import com.uduemc.biso.core.common.extities.CHostListCustomerData;
import com.uduemc.biso.core.common.extities.customerdata.CHostListData;
import com.uduemc.biso.core.extities.center.CustomerRole;
import com.uduemc.biso.core.extities.center.CustomerUser;
import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.core.extities.center.HostSetup;
import com.uduemc.biso.core.extities.center.Site;
import com.uduemc.biso.core.extities.center.SysHostType;
import com.uduemc.biso.core.extities.center.SysServer;
import com.uduemc.biso.core.extities.center.custom.CustomerUserRole;
import com.uduemc.biso.module.basic.service.common.mapper.CCustomDataMapper;
import com.uduemc.biso.module.basic.service.common.service.CCustomerService;
import com.uduemc.biso.module.basic.service.customer.mapper.CustomerUserMapper;
import com.uduemc.biso.module.basic.service.customer.service.CustomerRoleService;
import com.uduemc.biso.module.basic.service.customer.service.CustomerUserService;
import com.uduemc.biso.module.basic.service.service.HostService;
import com.uduemc.biso.module.basic.service.service.HostSetupService;
import com.uduemc.biso.module.basic.service.service.SysHostTypeService;
import com.uduemc.biso.module.basic.service.service.SysServerService;
import com.uduemc.biso.module.basic.service.service.impl.SiteServiceImpl;

import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

@Service
public class CCustomerServiceImpl implements CCustomerService {

	@Autowired
	private CustomerUserService customerUserServiceImpl;

	@Autowired
	private CustomerRoleService customerRoleServiceImpl;

	@Autowired
	private HostService hostServiceImpl;

	@Autowired
	private HostSetupService hostSetupServiceImpl;

	@Autowired
	private SysHostTypeService sysHostTypeServiceImpl;

	@Autowired
	private SysServerService sysServerServiceImpl;

	@Autowired
	private SiteServiceImpl siteServiceImpl;

	@Autowired
	private CustomerUserMapper customerUserMapper;

	@Autowired
	private CCustomDataMapper cCustomDataMapper;

	@Override
	@Transactional
	synchronized public CCustomerData append(CCustomerData customerData) {
		CustomerUser customerUser = customerData.getCustomerUser();

		// 用户
		// 通过用户名是否能够找到数据，
		String username = customerUser.getUsername();
		CustomerUser findByUsername = customerUserServiceImpl.findByUsername(username);
		if (findByUsername != null) {
			throw new RuntimeException("用户名已存在，不能添加！");
		}
		// 是否存在数字账号，如果存在则对数字账号进行是否重复校验
		String numberKey = customerUser.getNumberKey();
		if (StringUtils.hasText(numberKey)) {
			CustomerUser findByNumberKey = customerUserServiceImpl.findByNumberKey(numberKey);
			if (findByNumberKey != null) {
				throw new RuntimeException("数字账号已经存在已存在，不能添加！");
			}
		} else {
			// 生成数字账号
			String createNumberKey = customerUserServiceImpl.getCreateNumberKey();
			customerUser.setNumberKey(createNumberKey);
		}
		// 默认为非代理用户
		Long agentId = customerUser.getAgentId();
		if (agentId == null) {
			customerUser.setAgentId(0L);
		}

		// 写入 CustomerUser 数据
		CustomerUser insertCustomerUser = customerUserServiceImpl.insert(customerUser);

		// 如果写入失败则抛出异常
		if (insertCustomerUser == null || insertCustomerUser.getId() == null
				|| insertCustomerUser.getId().longValue() < 1) {
			throw new RuntimeException("创建 CustomerUser 失败 CustomerUser: " + customerUser.toString());
		}

		// CustomerRole 数据写入
		List<CustomerRole> customerRoles = customerData.getCustomerRoles();
		if (CollectionUtils.isEmpty(customerRoles)) {
			throw new RuntimeException("创建 CustomerRole 数据时发现 customerRoles 为空，根本没有任何数据！");
		}
		List<CustomerRole> insertCustomerRole = new ArrayList<>();
		Iterator<CustomerRole> iteratorCustomerRole = customerRoles.iterator();
		while (iteratorCustomerRole.hasNext()) {
			CustomerRole next = iteratorCustomerRole.next();
			next.setCustomerUserId(insertCustomerUser.getId());
			CustomerRole insert = customerRoleServiceImpl.insert(next);
			if (insert == null) {
				throw new RuntimeException("创建 CustomerRole 失败 CustomerRole: " + next.toString());
			}
			insertCustomerRole.add(insert);
		}

		// 站点
		Host host = customerData.getHost();

		// host type
		Long typeId = host.getTypeId();
		if (typeId == null) {
			throw new RuntimeException("host.typeId 不能为空！");
		}
		SysHostType findOne = sysHostTypeServiceImpl.findOne(typeId);
		if (findOne == null) {
			throw new RuntimeException("通过 host.typeId 找不到对应的数据！");
		}

		host.setUserId(insertCustomerUser.getId());

		// host server 部分
		Long serverId = host.getServerId();
		if (serverId == null) {
			throw new RuntimeException("host.serverId 不能为空！");
		}
		SysServer server = sysServerServiceImpl.findOne(serverId);
		if (server == null || server.getType() == null || server.getType().intValue() != 0 || server.getStatus() == null
				|| server.getStatus().shortValue() != (short) 1) {
			throw new RuntimeException("通过 host.serverId 找不到真实，可用的server的数据！");
		}

		// 验证 randomCode ，如果存在则验证是否重复，如果不存在，则生成一个新的可用的 rendomCode
		String randomCode = host.getRandomCode();
		if (StringUtils.hasText(randomCode)) {
			Host findByRandomCode = hostServiceImpl.findByRandomCode(randomCode);
			if (findByRandomCode != null) {
				// 已经被使用了
				throw new RuntimeException("通过 host.randomCode 已经被使用了！ randomCode: " + randomCode);
			}
		} else {
			String createRandomCode = hostServiceImpl.getCreateRandomCode(insertCustomerUser.getId());
			host.setRandomCode(createRandomCode);
		}

		Host insertHost = hostServiceImpl.insert(host);
		// 如果写入失败则抛出异常
		if (insertHost == null || insertHost.getId() == null || insertHost.getId().longValue() < 1) {
			throw new RuntimeException("创建 Host 失败 Host: " + host.toString());
		}

		// host setup 部分
		HostSetup hostSetup = new HostSetup();
		BeanUtils.copyProperties(findOne, hostSetup, "id", "name");
		hostSetup.setHostId(insertHost.getId());

		HostSetup findInfoByHostId = hostSetupServiceImpl.findInfoByHostId(insertHost.getId());
		if (findInfoByHostId != null) {
			throw new RuntimeException("通过 hostId 查询 HostSetup 数据发现已存在，hostId: " + insertHost.getId());
		}

		HostSetup insertHostSetup = hostSetupServiceImpl.insert(hostSetup);
		// 如果写入失败则抛出异常
		if (insertHostSetup == null || insertHostSetup.getId() == null || insertHostSetup.getId().longValue() < 1) {
			throw new RuntimeException("创建 HostSetup 失败 HostSetup: " + hostSetup.toString());
		}

		// site 部分
		List<Site> sites = customerData.getSites();
		if (CollectionUtils.isEmpty(sites)) {
			throw new RuntimeException("创建 Site 数据时发现 sites 为空，根本没有任何数据！");
		}
		List<Site> insertSite = new ArrayList<>();
		Iterator<Site> iterator = sites.iterator();
		while (iterator.hasNext()) {
			Site next = iterator.next();
			next.setHostId(insertHost.getId());
			Site insert = siteServiceImpl.insert(next);
			if (insert == null || insert.getId() == null || insert.getId().longValue() < 1) {
				throw new RuntimeException("创建 Site 失败 Site: " + next.toString());
			}
			insertSite.add(insert);
		}

		// set 数据
		customerData.setCustomerUser(insertCustomerUser).setCustomerRoles(insertCustomerRole).setHost(insertHost)
				.setHostSetup(insertHostSetup).setSites(insertSite);

		return customerData;
	}

	@Override
	public CHostListCustomerData info(long id, long agentId) {
		Example example = new Example(CustomerUser.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("id", id);
		criteria.andEqualTo("agentId", agentId);
		CustomerUser selectOneByExample = customerUserMapper.selectOneByExample(example);
		if (selectOneByExample == null) {
			return null;
		}
		CHostListCustomerData makeCCustomerData = makeCCustomerData(selectOneByExample);
		return makeCCustomerData;
	}

	@Override
	public PageInfo<CHostListCustomerData> infos(long agentId, String username, String numberKey, short status,
			int pageNumber, int pageSize) {
		PageHelper.startPage(pageNumber, pageSize);
		List<CHostListCustomerData> listCHostListCustomerData = cCustomDataMapper
				.findCHostListCustomerDataInfos(agentId, username, numberKey, status, "`customer_user`.`id` ASC");
		if (CollectionUtils.isEmpty(listCHostListCustomerData)) {
			return null;
		}
		for (CHostListCustomerData cHostListCustomerData : listCHostListCustomerData) {
			CustomerUser customerUser = cHostListCustomerData.getCustomerUser();
			CHostListCustomerData makeCCustomerData = makeCCustomerData(customerUser);

			List<CustomerUserRole> customerRoles = makeCCustomerData.getCustomerRoles();
			List<CHostListData> hostList = makeCCustomerData.getHostList();

			cHostListCustomerData.setCustomerRoles(customerRoles);
			cHostListCustomerData.setHostList(hostList);
		}

		PageInfo<CHostListCustomerData> pageInfo = new PageInfo<>(listCHostListCustomerData);

		return pageInfo;
	}

	protected CHostListCustomerData makeCCustomerData(CustomerUser customerUser) {
		CHostListCustomerData customerData = new CHostListCustomerData();
		customerData.setCustomerUser(customerUser);

		List<CustomerUserRole> customerRoles = customerRoleServiceImpl
				.findCustomerUserRoleByCustomerId(customerUser.getId());
		customerData.setCustomerRoles(customerRoles);

		List<Host> listHost = hostServiceImpl.findByUserId(customerUser.getId());
		if (!CollectionUtils.isEmpty(listHost)) {
			List<CHostListData> listCHostListData = new ArrayList<>();
			for (Host host : listHost) {
				CHostListData makeCHostListData = makeCHostListData(host);
				listCHostListData.add(makeCHostListData);
			}
			customerData.setHostList(listCHostListData);
		}

		return customerData;
	}

	protected CHostListData makeCHostListData(Host host) {
		CHostListData cHostListData = new CHostListData();
		cHostListData.setHost(host);

		HostSetup hostSetup = hostSetupServiceImpl.findInfoByHostId(host.getId());
		cHostListData.setHostSetup(hostSetup);

		List<Site> sites = siteServiceImpl.findByHostId(host.getId());
		cHostListData.setSites(sites);

		return cHostListData;
	}

}
